﻿using System;
using System.Collections.Generic;
using System.Text;
using ShootSearch.Core;
using ShootSearch.Common;
using System.Text.RegularExpressions;
using ShootSearch.Util;
using System.Diagnostics;

namespace ShootSearch.Parsers
{
    public class RegexFilter : IFilter
    {
        protected RegexFilterConfig config = new RegexFilterConfig();

        public RegexFilter()
        {
            ContentType = new List<string>();
            Extensions = new List<string>();

            ContentType.Add("text/html");
            ContentType.Add("text/xhtml");

        }

        protected void MatchRule(List<Rule> rules, ref string pageSource, ref ObjectItem item)
        {
            for (int i = 0; i < rules.Count; i++)
            {
                Match match = rules[i].Match(pageSource);
                if (!string.IsNullOrEmpty(rules[i].GroupName) && match.Groups[rules[i].GroupName].Success)
                {
                    string value = match.Groups[rules[i].GroupName].Value;
                    //Convert html to text
                    if(!rules[i].OutputHtml)
                    {
                        value = WebPage.Html2Text(value);
                    }
                    //Format to the output format
                    if (!string.IsNullOrEmpty(rules[i].OutputFormat))
                    {
                        try
                        {
                            value = string.Format(rules[i].OutputFormat, value);
                        }
                        catch (Exception ex)
                        {
                            Trace.WriteLine(ex);
                        }
                    }

                    item[rules[i].GroupName] = value ;

                  
                }
                
                //Continue to match the sub rules
                if (match.Success && rules[i].Children.Count>0)
                {
                    string subSource = match.Value;
                    MatchRule(rules[i].Children, ref subSource, ref item);
                }
            

            }
        }

        #region IConfigable Members

        public SpiderManConfig Config
        {
            get { return config; }
            set
            {
                if (value is RegexFilterConfig)
                    config = value as RegexFilterConfig;
            }
        }

        #endregion

        #region IFilter Members

        public List<string> Extensions { get; protected set; }
        public List<string> ContentType { get; protected set; }

        public bool Parse(string url, Encoding encoding, string contentType, byte[] content, out object doc)
        {
            doc = null;
            if (config == null) return false;
            string pageSource = encoding.GetString(content);

            ObjectItem item = new ObjectItem(url);

            for (int i = 0; i < config.Rules.Count; i++)
            {
                PageRule rule = config.Rules[i];
                bool matchUrl = rule.Rule.IsMatch(url);

                bool matchPage = false;
                //Only url matched
                if ((rule.Type == PageRuleType.UrlOnly ||
                    rule.Type == PageRuleType.Either) && matchUrl)
                {
                    MatchRule(rule.Rule.Children, ref pageSource, ref item);
                    if (!rule.CanContinue) break;
                }

                matchPage = rule.Rule.IsMatch(pageSource);

                //Only url matched
                if (rule.Type == PageRuleType.PageSourceOnly ||
                        rule.Type == PageRuleType.Either && matchPage)
                {
                    MatchRule(rule.Rule.Children, ref pageSource, ref item);
                    if (!rule.CanContinue) break;

                }

                //Both url && pagesource
                if (rule.Type == PageRuleType.Both && matchUrl && matchPage)
                {
                    MatchRule(rule.Rule.Children, ref pageSource, ref item);
                    if (!rule.CanContinue) break;
                }


            }
            if (item.Count > 0)
            {
                doc = item;
                return true;
            }
            else return false;


        }

        #endregion
    }
}
